import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import math

import tensorflow.keras as keras
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from sklearn.model_selection import train_test_split
from tensorflow.keras.regularizers import l2
from sklearn.metrics import mean_absolute_error, make_scorer
from sklearn.metrics import mean_absolute_percentage_error, adjusted_rand_score
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error

from src.python.util.getResoures import getData


def run():
    # 获取数据
    x_train, x_test, y_train, y_test = getData()
    # 数据预处理
    x_train = np.array(x_train).reshape(444, 60, 1)
    y_train = np.array(y_train).reshape(444, 2, 1)
    x_test = np.array(x_test).reshape(191, 60, 1)
    y_test = np.array(y_test).reshape(191, 2, 1)
    # 定义CNN卷积神经网络回归预测模型
    model = keras.Sequential([
        # 卷积层
        keras.layers.Conv1D(filters=64  # 卷积核个数
                            , kernel_size=3  # 卷积核尺寸 一维
                            , strides=1  # 步长为1
                            , padding='same'  # 补零策略(边缘填充方法)
                            , activation='relu'  # 激活函数
                            , input_shape=(60, 1)  # 输入
                            # ,kernel_regularizer=l2(0.0001) # l2正则化，缓解过拟合
                            ),
        # 最大池化层
        keras.layers.MaxPool1D(pool_size=2, padding='same'),
        # 卷积层
        keras.layers.Conv1D(filters=32  # 卷积核个数
                            , kernel_size=3  # 一维
                            , strides=1  # 步长为1
                            , padding='same'  # 补零策略
                            , activation=None  # 激活函数
                            ),
        # 最大池化层
        keras.layers.MaxPool1D(pool_size=2, padding='same'),
        # 展平层
        keras.layers.Flatten(),
        # 全连接层
        keras.layers.Dense(activation=None, units=60),
        # 批标准化层
        keras.layers.BatchNormalization(),
        # 全连接层
        keras.layers.Dense(activation=None, units=2)
    ])
    # 定义优化器
    # optimizers = tf.optimizers.Adam(learning_rate=0.05)
    optimizers = tf.compat.v1.train.AdamOptimizer(learning_rate=0.005, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False, name='Adam')
    # 模型编译
    model.compile(optimizer= optimizers # 优化器
                  , loss=tf.losses.mean_squared_error
                  , metrics=['mse']
                  )
    # 模型训练
    print("------------------------------------------- CNN卷积神经网络回归预测模型：-------------------------------------------")
    model.fit(x_train, y_train # 训练集
              , epochs = 1000 # 迭代次数
              , verbose = False # 是否输出迭代信息
              , shuffle = True  # 对数据进行打乱 最好设置为True，否则准确率一般很低
              )
    # 模型预测
    y_pre = model.predict(x_test)
    # 将测试集的y改回原来的形状
    y_test = y_test.reshape(191, 2)
    # 评估分数
    mae = mean_absolute_error(y_pred=y_pre, y_true=y_test)
    print("平均绝对误差MAE:", mae)
    mse = mean_squared_error(y_pred=y_pre, y_true=y_test)
    print("均方根误差RMSE:", math.sqrt(mse))
    print("均方误差MSE:", mse)
    mape = mean_absolute_percentage_error(y_pred=y_pre, y_true=y_test)
    print("平均绝对百分比误差MAPE:", mape)


if __name__ == "__main__":
    run()
